#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <cerrno>
#include <cstdio>

#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define BaseSize 4096

const std::string comm_path = "./myfifo";

// // 创建命名管道
// int CreateNamedPipe()
// {
//     int res = mkfifo(comm_path.c_str(), 0666);
//     // 返回值不等于0则创建失败
//     if (res != 0)
//     {
//         perror("mkfifo");
//     }
//     return res;
// }

// // 删除管道文件
// int RemoveNamedPipe(const std::string &path)
// {
//     int res = unlink(path.c_str());
//     if (res != 0)
//     {
//         perror("umlink");
//     }
//     return res;
// }

class NamePiped
{
private:
    bool OpenNamedPipe(int mode)
    {
        // 返回值是文件描述符，打开失败返回-1，并设置错误码
        _fd = open(_fifo_path.c_str(), mode);
        if (_fd < 0)
            return false;
        return true;
    }

public:
    // 构造函数创建管道
    NamePiped(const std::string &path, int who)
        : _fifo_path(path), _id(who), _fd(DefaultFd)
    {
        // 创建着才需要创建管道
        if (_id == Creater)
        {
            int res = mkfifo(_fifo_path.c_str(), 0666);
            // 返回值不等于0则创建失败
            if (res != 0)
            {
                perror("mkfifo");
            }
            std::cout << "creater create named pipe" << std::endl;
        }
    }
    // 以读方式打开文件
    bool OpenForRead()
    {
        return OpenNamedPipe(Read);
    }
    // 以写方式打开文件
    bool OpenForWrite()
    {
        return OpenNamedPipe(Write);
    }
    // 读文件
    int ReadNamedPipe(std::string *out)
    {
        char buffer[BaseSize];
        int n = read(_fd, buffer, sizeof(buffer));
        if (n > 0)
        {
            buffer[n] = 0;
            *out = buffer;
        }
        return n;
    }
    // 写文件
    int WriteNamedPipe(const std::string& in)
    {
        return write(_fd,in.c_str(),in.size());
    }
    // 析构函数删除管道
    ~NamePiped()
    {
        // 析构之前休眠5秒，看删除效果
        sleep(5);
        // 创建者才需要删除管道
        if (_id == Creater)
        {
            int res = unlink(_fifo_path.c_str());
            if (res != 0)
            {
                perror("umlink");
            }
            std::cout << "creater free named pipe" << std::endl;
        }
        // 创建了文件则关闭文件描述符
        if(_fd != DefaultFd) close(_fd);
    }

private:
    const std::string _fifo_path; // 文件路径
    int _id;                      // 用户名
    int _fd;                      // 文件描述符
};